package com.zx.service;/**
 * Author:JasonZ
 * Data:2023/4/17
 */

import cn.hutool.crypto.digest.MD5;
import com.alibaba.fastjson.JSON;
import com.zx.constant.AuthorityConstant;
import com.zx.dao.ECommerceUserDao;
import com.zx.entity.ECommerceUser;
import com.zx.model.dto.UserToken;
import com.zx.model.vo.LoginUserInfo;
import com.zx.model.vo.UsernameAndPassword;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.Date;

/**
 * @program: ecommerce-parent
 * @description:
 * @author: JasonZ
 * @create: 2023-04-17 10:12
 **/
@Service
@Slf4j
public class AuthorityService {
    @Resource
    private ECommerceUserDao userDao;

    /*登录校验获取token凭证*/
    public UserToken login(UsernameAndPassword usernameAndPassword) throws Exception {
        //1.查询当前用户
        ECommerceUser currentUser = userDao.findByUsername(usernameAndPassword.getUsername());
        if (currentUser == null) {
            throw new RuntimeException("用户不存在");
        }
        if (!currentUser.getPassword().equalsIgnoreCase(MD5.create().digestHex(usernameAndPassword.getPassword()))) {
            throw new RuntimeException("密码错误");
        }
        //2.密码正确 构建凭证
        String token = Jwts.builder()
                // 构建时间
                .setIssuedAt(new Date())
                //设置过期时间
                .setExpiration(new Date(System.currentTimeMillis() + AuthorityConstant.EXP_TIME.toMillis()))
                //自定义存入的用户对象
                .claim(AuthorityConstant.ECOMMERCE_USER_KEY,
                        JSON.toJSONString(new LoginUserInfo(currentUser.getId(), currentUser.getUsername()))
                )
                // 根据私钥，和算法(RSA)
                .signWith(getPrivateKey(), SignatureAlgorithm.RS256)
                //拼接
                .compact();
        return new UserToken(currentUser.getId(), token);
    }

    public UserToken register(UsernameAndPassword usernameAndPassword) throws Exception {
        // 查询用户名是否已经存在
        ECommerceUser currentUser = userDao.findByUsername(usernameAndPassword.getUsername());
        if(currentUser!=null){
            log.error("用户名已经存在！");
            throw new RuntimeException("用户已经存在！");
        }

        // 瞬时对象
        ECommerceUser user = new ECommerceUser();
        user.setUsername(usernameAndPassword.getUsername());
        user.setPassword(MD5.create().digestHex(usernameAndPassword.getPassword()));
        user.setExtraInfo("{}");
        // 持久化
        // mybatisPlus'
        // Hibernate: 瞬时状态， 持久状态， 游离状态
        // userInDB 持久对象
        // 在提交事务以前对持久对象做仍和修改以后，在事务提交的时候会提交响应的修改SQL语句
        ECommerceUser userInDB = userDao.save(user);
        // 生成凭证
        String token =Jwts.builder().
                // 构建时间
                        setIssuedAt(new Date())
                // 过期时间
                .setExpiration(new Date(System.currentTimeMillis()+AuthorityConstant.EXP_TIME.toMillis()))
                // 自定义存入的用户对象
                .claim(AuthorityConstant.ECOMMERCE_USER_KEY,
                        JSON.toJSONString(new LoginUserInfo(userInDB.getId(),userInDB.getUsername())))
                // 根据私钥，和算法(RSA)
                .signWith(getPrivateKey(), SignatureAlgorithm.RS256).compact();
        return new UserToken(
                userInDB.getId(),
                token
        );
    }

    private PrivateKey getPrivateKey() throws Exception {
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new
                PKCS8EncodedKeySpec(Base64.getDecoder().decode(AuthorityConstant.PRIVATE_KEY));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(pkcs8EncodedKeySpec);
    }


}
